package nobnak.study.gl;

import java.util.LinkedList;
import java.util.List;

import javax.microedition.khronos.opengles.GL10;

import nobnak.study.gl.BezierCurveModel.PointManipulator;
import nobnak.study.gl.BezierCurveRenderer.VertexBufferElement;
import nobnak.study.gl.Delegate.Action0;
import nobnak.study.gl.Delegate.Function0;
import nobnak.study.gl.LineCliping.Clip;
import nobnak.study.gl.PluggableGLSurfaceView.RenderTask;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.Display;
import android.view.MotionEvent;
import android.view.View;

public class StudyGLActivity extends Activity {
	public static final String LOG_TAG = "StudyGL";
	public static final float[] COLOR_WHITE = new float[] { 1.0f, 1.0f, 1.0f, 1.0f };
	public static final float[] COLOR_RED   = new float[] { 1.0f, 0.0f, 0.0f, 1.0f };
	public static final float[] COLOR_GREEN = new float[] { 0.0f, 1.0f, 0.0f, 1.0f };
	public static final float[] COLOR_BLUE  = new float[] { 0.0f, 0.0f, 1.0f, 1.0f };
	
	private PluggableGLSurfaceView glView;
	private LineCliping clipping;
	private float[] clipRect;
	
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        this.glView = (PluggableGLSurfaceView) findViewById(R.id.pluggableGLSurfaceView1);
        
        Display display = getWindowManager().getDefaultDisplay();
        float width = display.getWidth(), height = display.getHeight();
        float left = width * 0.25f, right = width * 0.75f;
        float bottom = height * 0.25f, top = height * 0.75f;
        this.clipping = new LineCliping(left, right, bottom, top);
        this.clipRect = new float[] { left, bottom, right, bottom, right, top, left, top };

        BezierCurveBuilder bezierBuilder = new BezierCurveBuilder(0.5f);
        float[] p = new float[] {30f, 50f, 50f, 150f, 150f, 150f, 170f, 50f};
    	final BezierCurveModel bezierModel = new BezierCurveModel(bezierBuilder, p); 
    	List<RenderTask> registerTasks = new LinkedList<PluggableGLSurfaceView.RenderTask>();
    	final Function0<List<RenderTask>> unregisterCurve = registerCurve(bezierModel, registerTasks);
    	glView.doTasks(registerTasks);

        glView.setOnTouchListener(new PluggableGLSurfaceView.OnTouchListener() {
        	private boolean touching = false;
        	private Function0<List<RenderTask>> unregiAction0 = unregisterCurve;
        	private float currX, currY;
        	private PointManipulator pointManip;
        	
			@Override
			public boolean onTouch(View v, MotionEvent event) {

				switch (event.getAction()) {
				case MotionEvent.ACTION_MOVE:
					if (pointManip == null || !touching)
						break;
					float dX = event.getX() - currX, dY = event.getY() - currY;
					currX = event.getX();
					currY = event.getY();
					List<RenderTask> tasks = unregiAction0.call();
					pointManip.move(dX, -dY);
					unregiAction0 = registerCurve(bezierModel, tasks);
					glView.doTasks(tasks);
					break;
				case MotionEvent.ACTION_DOWN:
					touching = true;
					currX = event.getX();
					currY = event.getY();
					int indexPoint = bezierModel.findNearestPoint(currX, glView.getHeight() - currY);
					pointManip = bezierModel.makePointManipulator(indexPoint);
					break;
				case MotionEvent.ACTION_UP:
					touching = false;
					break;
				}
				return true;
			}
			});
    }
	private Function0<List<RenderTask>> registerCurve(BezierCurveModel bezierModel, List<RenderTask> registerTasks) {
		float[] strip = bezierModel.tessellate();
		Clip[] clips = clipping.clipStrip(strip);
		float[] clipedLines = new float[clips.length * 4];
		for (int i = 0; i < clips.length; i++) {
			Clip clip = clips[i];
			clipedLines[i * 4] = clip.x0;
			clipedLines[i * 4 + 1] = clip.y0;
			clipedLines[i * 4 + 2] = clip.x1;
			clipedLines[i * 4 + 3] = clip.y1;
		}

		final VertexBufferElement stripVertices = new VertexBufferElement(GL10.GL_LINE_STRIP, strip, COLOR_BLUE);
		final VertexBufferElement pointVertices = new VertexBufferElement(GL10.GL_POINTS, bezierModel.getPoints(), COLOR_WHITE);
		final VertexBufferElement clipedLineVertices = new VertexBufferElement(GL10.GL_LINES, clipedLines, COLOR_RED);
		final VertexBufferElement rectVertices = new VertexBufferElement(GL10.GL_LINE_LOOP, clipRect, COLOR_WHITE);
		
		registerTasks.add(glView.makeTaskAddVertexElement(stripVertices));
        registerTasks.add(glView.makeTaskAddVertexElement(pointVertices));
        registerTasks.add(glView.makeTaskAddVertexElement(clipedLineVertices));
        registerTasks.add(glView.makeTaskAddVertexElement(rectVertices));
		return new Function0<List<RenderTask>>() {
			@Override
			public List<RenderTask> call() {
				List<RenderTask> result = new LinkedList<PluggableGLSurfaceView.RenderTask>();
				result.add(glView.makeTaskRemoveVertexElement(stripVertices));
				result.add(glView.makeTaskRemoveVertexElement(pointVertices));
				result.add(glView.makeTaskRemoveVertexElement(clipedLineVertices));
				result.add(glView.makeTaskRemoveVertexElement(rectVertices));
				return result;
			}
		};
	}
}